from sklearn.datasets import load_breast_cancer
import numpy as np
import matplotlib.pyplot as plt
import sys


def model(x, theta):
    return x.dot(theta)


def sigmoid(z):
    return 1.0 / (1.0 + np.exp(-z))


def cost(h, y):
    m = len(y)
    return -1.0/m * np.sum(y*np.log(h) + (1-y)*np.log(1-h))

def grad(x, y, iter0=5000, alpha=0.01):
    m, n = x.shape
    theta = np.zeros(n)
    J = np.zeros(iter0)

    for i in range(iter0):
        z = model(x, theta)
        h = sigmoid(z)
        J[i] = cost(h, y)
        dt = 1.0/m * x.T.dot(h - y)
        theta -= alpha * dt
    return h, theta, J


def score(h, y):
    """准确率"""
    return np.mean(y == (h > 0.5))


if '__main__' == __name__:
    np.random.seed(1)
    cancer = load_breast_cancer()
    x = cancer.data
    y = cancer.target
    m = len(x)
    print(x[:5])
    sys.exit(0)

    # standardization
    mu = np.mean(x, axis=0)
    sigma = np.std(x, axis=0)
    x -= mu
    x /= sigma

    # shuffle
    X = np.c_[np.ones(m), x]
    a = np.random.permutation(m)
    X = X[a]
    y = y[a]

    num = int(0.7 * m)
    train_x, test_x = np.split(X, [num])
    train_y, test_y = np.split(y, [num])

    train_h, theta, J = grad(train_x, train_y)
    plt.plot(J)
    plt.show()

    print(f'train score: {score(train_h, train_y)}')

    test_h = sigmoid(model(test_x, theta))
    print(f'test score: {score(test_h, test_y)}')
